package com.test.liuhb.test.Gson;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.TextView;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.test.liuhb.test.Adapter.UserTypeAdapter;
import com.test.liuhb.test.R;
import com.test.liuhb.test.entity.Result;
import com.test.liuhb.test.entity.User;
import com.test.liuhb.test.entity.Users;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by liu.hb on 2018/2/22.
 */
//1.设置布局
@EActivity(R.layout.item_gsonlayout)
public class GsonTest4 extends Activity{
    //2.实例化控件
    @ViewById(R.id.textView)
    TextView tv;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userTest();
        userTest1();
        GsonTest2();
        GsonTest3();
        GsonTest4();
        GsonTest5();
        GsonTest6();
    }
    //3.初始化控件显示
    @AfterViews
    void initViews() {
        // 初始化控件
        tv.setText("Gson使用指南（四）");
    }
    /**
     * 一、TypeAdapter
     * 注意：TypeAdapter 以及 JsonSerializer 和 JsonDeserializer
     * 都需要与 GsonBuilder.registerTypeAdapter 示或GsonBuilder.registerTypeHierarchyAdapter配合使用
     */
    public void userTest(){
        Users user = new Users("liu.hb", 24);
        user.email = "liu.hb@qq.com";
        Gson gson = new GsonBuilder() //为Users注册TypeAdapter
        .registerTypeAdapter(User.class, new UserTypeAdapter()) .create();
        System.out.println("-----------TypeAdapter序列化---------------------");
        Log.d("System.out","Log.d =>>>>>"+gson.toJson(user));
        System.out.println(gson.toJson(user));
    }
    /**
     * 二、JsonSerializer与JsonDeserializer
     * 测试空串的时候一定是"\"\""而不是""，""代表的是没有json串，"\"\""才代表json里的""。
     */
    public void userTest1(){
        Gson gson = new GsonBuilder() .registerTypeAdapter(Integer.class,
                new JsonDeserializer<Integer>() {
                    @Override
                    public Integer deserialize(JsonElement json, Type typeOfT,
                                               JsonDeserializationContext context)
                            throws JsonParseException {
                        try {
                            return json.getAsInt();
                        } catch (NumberFormatException e)
                        { return -1;
                        }
                    }
        }) .create();
        System.out.println("----------------测试空字符串-------------------------");
        System.out.println(gson.toJson(100)); //结果：100
        System.out.println(gson.fromJson("\"\"", Integer.class)); //结果-1
    }
    /**
     * 二、JsonSerializer与JsonDeserializer
     * 所有数字都转成序列化为字符串的例子
     *registerTypeAdapter必须使用包装类型,同时不能使用父类来替上面的子类型
     */
    public void GsonTest2(){
        JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() {
            @Override
            public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext context) {
                return new JsonPrimitive(String.valueOf(src));
            }
        };
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Integer.class, numberJsonSerializer)
                .registerTypeAdapter(Long.class, numberJsonSerializer)
                .registerTypeAdapter(Float.class, numberJsonSerializer)
                .registerTypeAdapter(Double.class, numberJsonSerializer)
                .create();
        System.out.println("----------所有数字都转成序列化为字符串--------------------");
        System.out.println(gson.toJson(100.0f));//结果："100.0"
        System.out.println(gson.toJson(100.223344d));//结果："100.223344"

    }
    /**
     * 二、JsonSerializer与JsonDeserializer
     * 注：如果一个被序列化的对象本身就带有泛型，且注册了相应的TypeAdapter，
     * 那么必须调用Gson.toJson(Object,Type)，明确告诉Gson对象的类型。
     */
    public void GsonTest3(){
        Type type = new TypeToken<List<Users>>() {}.getType();
        TypeAdapter typeAdapter = new TypeAdapter<List<Users>>()
        {
            @Override
            public void write(JsonWriter out, List<Users> value) throws IOException {
                out.beginObject();
                //赋值
                for(Users u:value){
                    out.name("name").value(u.name);
                    out.name("age").value(u.age);
                    out.name("email").value(u.email);
                }
                out.endObject();
            }
            @Override
            public List<Users> read(JsonReader in) throws IOException {
                return null;
            }
        };
         Gson gson = new GsonBuilder() .registerTypeAdapter(type, typeAdapter) .create();
        List<Users> list = new ArrayList<>();
        list.add(new Users("a",11));
        list.add(new Users("b",22));
        //注意，多了个type参数
        System.out.println("----------调用Gson.toJson(Object,Type)，明确告诉Gson对象的类型--------------------");
        System.out.println(gson.toJson(list, type));//结果："100.0"
    }
    /**
     * 三、TypeAdapterFactory
     *创建TypeAdapter的工厂类，通过对比Type，确定有没有对应的TypeAdapter，
     * 没有就返回null，与GsonBuilder.registerTypeAdapterFactory配合使用。
     */
    public void GsonTest4(){
        Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new TypeAdapterFactory() {
            @Override
            public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type)
            {
                return null;
            } }) .create();
        //不知道怎么使用
        System.out.println("----------TypeAdapter的工厂类--------------------");
        System.out.println(gson.toJson(100.0f));//结果："100.0"
    }
    /**
     * 四、@JsonAdapter注解
     *创建TypeAdapter的工厂类，通过对比Type，确定有没有对应的TypeAdapter，
     * 没有就返回null，与GsonBuilder.registerTypeAdapterFactory配合使用。
     */
    public void GsonTest5(){
        Gson gson = new Gson();
        Users user1 = new Users("怪盗kidou", 24, "ikidou@example.com");
        System.out.println("----------@JsonAdapter注解--------------------");
        System.out.println(gson.toJson(user1));
        //结果：{"name":"怪盗kidou","age":24,"email":"ikidou@example.com"}
        //不加@JsonAdapter注解结果： {"name":"怪盗kidou","emailAddress":"ikidou@example.com","age":24}
        // 为区别结果，特意把email字段与@SerializedName注解中设置的不一样
    }
    /**
     * 六、TypeAdapter实例
     *服务器返回的数据中data字段类型不固定，比如请求成功data是一个List,不成功的时候是String类型
     */
    public void GsonTest6(){
        Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(List.class,
                new JsonDeserializer<List<?>>() {
                    @Override
                    public List<?> deserialize(JsonElement json, Type typeOfT,
                                               JsonDeserializationContext context)
                            throws JsonParseException {
                        if (json.isJsonArray()) {
                            JsonArray array = json.getAsJsonArray();
                            Type itemType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
                            List list = new ArrayList<>();
                            for (int i = 0; i < array.size(); i++) {
                                JsonElement element = array.get(i);
                                Object item = context.deserialize(element, itemType);
                                list.add(item);
                            } return list;
                        } else { //和接口类型不符，返回空List
                              return Collections.EMPTY_LIST;
                        }
                    }
        }).create();
        User u=new User("怪盗kidou",24,"长沙市");
        Result<User> result = new Result<User>(0,"message",u);
        String json = gson.toJson(result);
//        String json = "{\"name\":\"怪盗kidou\",\"age\":24}";
        Type userType = new TypeToken<Result<User>>(){}.getType();
        Result<User> userResult = gson.fromJson(json,userType);
        User user = userResult.data;
        System.out.println("-------------同一个接口任何情况下不得改变返回类型，要么就不要返，要么就返空值----------");
        System.out.println("-------姓名："+user.name+";年龄："+user.age+";地址："+user.emailAddress);

    }

}
